package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"github.com/gogf/gf/net/gtcp"
	"github.com/gogf/gf/os/glog"
	"github.com/gogf/gf/os/gtime"
	"github.com/gogf/gf/os/gtimer"
	"github.com/gogf/gf/util/gconv"
	"github.com/gogf/gf/util/grand"
	"time"
)

func main() {
	glog.Info("启动服务")
	gtcp.NewServer(gconv.String(":30000"), func(conn *gtcp.Conn) {
		var mkey string
		var cTimer *gtimer.Entry
		mkey = fmt.Sprintf("%s-%s", conn.RemoteAddr().String(), grand.Digits(6))
		defer func() {
			conn.Close()
			cTimer.Close()
			glog.Infof("连接退出:%s", mkey)
		}()
		glog.Info("新的连接:", mkey)
		updateTime := gtime.Now().Second()
		cTimer = gtimer.Add(10*time.Second, func() {
			if gtime.Now().Second()-updateTime > 300 {
				glog.Info("心跳超时")
				conn.Close()
			}
		})
		bufferMax := 5000
		buffer := bytes.NewBuffer(make([]byte, 0, bufferMax))
		for {
			data, err := conn.Recv(-1)
			if err != nil {
				if err.Error() == "EOF" {
					glog.Notice("客户端关闭")
				}
				break
			}
			if (len(data) + buffer.Len()) > bufferMax {
				glog.Notice("缓冲数据溢出")
				continue
			}
			_, err = buffer.Write(data)
			if err != nil {
				glog.Info("Error writing to buffer", err.Error())
				buffer.Reset()
				continue
			}
			if len(buffer.Bytes()) > 0 {
				array := unpack(buffer.Bytes())
				for _, v := range array {
					l := make([]byte, v)
					buffer.Read(l)
					glog.Infof("读取数据%v", l)
					updateTime = gtime.Now().Second()
					//todo:数据解析到对象
				}
				//清洗数据
				if buffer.Len() > 0 {
					tl := make([]byte, buffer.Len())
					t2 := make([]byte, 0)
					buffer.Read(tl)
					buffer.Reset()
					start := false
					for i, v := range tl {
						if start == true {
							t2 = append(t2, v)
						} else {
							if v == 0x1c {
								if len(tl)-i >= 2 {
									if tl[i+1] == 0x03 {
										start = true
										t2 = append(t2, v)
									}
								} else {
									t2 = append(t2, v)
								}
							}
						}
					}
					if len(t2) > 0 {
						buffer.Write(t2)
					}
				}
			}
		}
	}).Run()
}

func unpack(bytes []byte) []int {
	dLen := len(bytes)
	var array = make([]int, 0)
	var need = 0
	var up = 0 //上次读取的个数
	for i, v := range bytes {
		//判断数据是否足够
		if need != 0 {
			need--
		} else {
			if dLen-i > 6 {
				if v == 0x1c && bytes[i+1] == 0x03 {
					offset := i + 2
					offset += 2 //偏移2个字节time
					fLen := binary.BigEndian.Uint16(bytes[offset : offset+2])
					offset += 2 //偏移2个字节长度
					need := 6 + int(fLen)
					array = append(array, i-up+need)
					up = i + need
					need -= 1 //补偿已经读取的0x1c
				} else {
					continue
				}
			} else {
				break
			}
		}
	}
	return array
}
